(function (Vue) {//表示依赖了全局的 Vue, 其实不加也可以，只是更加明确点,不能用vue 小写v
	var STORAGE_KEY = 'items-vuejs';
	// 本地存储数据对象
	const itemStorage = {
		fetch: function () {
			// 获取本地数据 
			return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
		},
		save: function (items) {
			// 保存数据到本地 
			localStorage.setItem(STORAGE_KEY, JSON.stringify(items));
		}
	}
	//初始化任务
	const items = [
		{
			id: 1,//主键id
			content: 'vue.js',//输入的内容
			completed: false//是否完成
		},
		{
			id: 2,//主键id
			content: 'java',//输入的内容
			completed: false//是否完成
		},
		{
			id: 3,//主键id
			content: 'python',//输入的内容
			completed: false//是否完成
		}
	]

	//自定义全局指令，用于 增加输入框 
	//定义时不要在前面加v-, 引用指令时要加上v- 
	Vue.directive('app-focus',
		{   //聚集元素 
			inserted(el, binding) {
				el.focus()
			}
		})

	var app = new Vue({
		el: '#todoapp',
		data: {
			items:itemStorage.fetch(),//等价于items:items
			currentItem: null, //上面不要少了逗号， 接收当前点击的任务项
			filterStatus: 'all' // 上面不要少了逗号，接收变化的状态值
		},

		// 监听器
		watch: {
			// 如果 items 发生改变，这个函数就会运行
			items:{
				deep: true, // 发现对象内部值的变化, 要在选项参数中指定 deep: true。
				handler: function(newItems, oldItems) { 
					//本地进行存储 
					itemStorage.save(newItems) 
				}
			}
		},

		//自定义局部指令，用于编辑输入框
		directives: {
			//定义时不要在前面加v-, 引用指令时要加上v-
			'todo-focus': {
				update(el, binding) { // 每当指令的值更新后，会调用此函数
					if (binding.value) {
						el.focus()
					}
				}
			}
		},
		// 定义计算属性
		computed: {
			// 过滤出不同状态数据
			filterItems() {
				//this.filterStatus 作为条件，变化后过滤不同数据 
				switch (this.filterStatus) {
					case "active":
						// 过滤出未完成的数据 
						return this.items.filter(item => !item.completed)
						break
					case "completed":
						// 过滤出已完成的数据 
						return this.items.filter(item => item.completed)
						break
					default:
						// 其他，返回所有数据 
						return this.items
				}
			},
			// 剩余未完成任务项
			remaining() {//等价于 remaining:function(){
				//数组函数filter过滤所有未完成的任务项
				//unitems 用于接收所有的未完成的任务项
				const unitems = this.items.filter(function (item) {
					return !item.completed
				})
				return unitems.length
			},
			//复选框计算属性(双向绑定)
			toggleAll: {
				get() { //等价于 get : functon () {...} 
					console.log(this.remaining)
					//2. 当 this.remaining 发生变化后，会触发该方法运行 
					// 当所有未完成任务数为 0 , 表示全部完成, 则返回 true 让复选框选中 
					//反之就 false 不选中 
					return this.remaining === 0
				},
				set(newStatus) {
					// console.log(newStatus) 
					//1. 当点击 checkbox 复选框后状态变化后，就会触发该方法运行, 
					// 迭代出数组每个元素,把当前状态值赋给每个元素的 completed 
					// 下面箭头函数等价于：this.items.forEach(function (item) { 
					this.items.forEach((item) => {
						item.completed = newStatus
					})
				}
			}
		},

		methods: {
			//编辑完成
			finishEdit(item, index, event) {
				const content = event.target.value.trim();
				// 1. 如果为空, 则进行删除任务项 
				if (!event.target.value.trim()) {
					//重用 removeItem 函数进行删除 
					this.removeItem(index)
					return
				}
				// 2. 添加数据到任务项中 ，实为更新任务项
				item.content = content
				// 3. 移除 .editing 样式 
				this.currentItem = null
			},
			//取消编辑
			cancelEdit() {
				// 移除样式 
				this.currentItem = null
			},
			// 进入编辑状态,当前点击的任务项item赋值currentItem，用于页面判断显示 .editing
			toEdit(item) {
				this.currentItem = item
			},
			//移除所有未完成任务项
			removeCompleted() {
				// 过滤出所有未完成的任务，重新赋值数组
				/*this.items = this.items.filter((item) => {
					return !item.completed
				})*/
				this.items = this.items.filter(item => !item.completed)
			},
			// 移除任务项
			removeItem(index) {
				// 移除索引为index的一条记录 
				this.items.splice(index, 1)
			},
			addItem(event) { //对象属性函数简写，等价于addItem: function (event) {
				console.log('addItem', event.target.value)
				//1. 获取文本框输入的数据 
				const content = event.target.value.trim()
				//2. 判断数据如果为空，则什么都不做 
				if (!content.length) {
					return
				}
				//3.如果不为空，则添加到数组中 
				// 生成id值 
				const id = this.items.length + 1
				this.items.push({
					id, //等价于 id:id 
					content,
					completed: false
				})
				//4. 清空文本框内容 
				event.target.value = ''
			}
		}
	})

	//当路由 hash 值改变后会自动调用此函数
	window.onhashchange = function () {
		console.log('hash改变了', window.location.hash)
		// 1.获取点击的路由 hash , 当截取的 hash 不为空返回截取的，为空时返回 'all' 
		const hash = window.location.hash.substr(2) || 'all'
		console.log('hash', hash)
		// 2. 状态一旦改变，将 hash 赋值给 filterStatus 
		// 当计算属性 filterItems 感知到 filterStatus 变化后，就会重新过滤 
		// 当 filterItems 重新过滤出目标数据后，则自动同步更新到视图中 
		app.filterStatus = hash
	}
	// 第一次访问页面时,调用一次让状态生效
	window.onhashchange()
})(Vue);
